﻿using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.IO;

namespace PrimaProvaCompilEXec
{
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.TextBox textBox2;
        private TextBox textBox3;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;


        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.button1 = new System.Windows.Forms.Button();
            this.textBox3 = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            // 
            // textBox2
            // 
            this.textBox2.Location = new System.Drawing.Point(271, 48);
            this.textBox2.Multiline = true;
            this.textBox2.Name = "textBox2";
            this.textBox2.Size = new System.Drawing.Size(229, 48);
            this.textBox2.TabIndex = 2;
            this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged);
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(16, 48);
            this.textBox1.Multiline = true;
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(240, 240);
            this.textBox1.TabIndex = 0;
            this.textBox1.Text = resources.GetString("textBox1.Text");
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(356, 128);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 1;
            this.button1.Text = "Run";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // textBox3
            // 
            this.textBox3.Location = new System.Drawing.Point(271, 185);
            this.textBox3.Multiline = true;
            this.textBox3.Name = "textBox3";
            this.textBox3.Size = new System.Drawing.Size(229, 117);
            this.textBox3.TabIndex = 3;
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(512, 325);
            this.Controls.Add(this.textBox3);
            this.Controls.Add(this.textBox2);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.textBox1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            Button ButtonObject = (Button)sender;
            CompilerResults results = null;
            String[] parameters = (String.Compare(textBox2.Text,"",false,System.Globalization.CultureInfo.InvariantCulture) != 0) ? textBox2.Text.Split(" ".ToCharArray()) : new String[0];
            Object[] param = null;
            using (var provider = new CSharpCodeProvider())
            {
                var options = new CompilerParameters();
                options.GenerateInMemory = true;
                results = provider.CompileAssemblyFromSource(options, textBox1.Text);
            }
            if (results.Errors.HasErrors)
            {
                var errorMessage = new StringBuilder();
                foreach (CompilerError error in results.Errors)
                {
                    errorMessage.AppendFormat("{0} {1}", error.Line, error.ErrorText);
                }
                textBox3.Text = errorMessage.ToString();
                return;
            } 
            //If we clicked run then launch our EXE
            //if (ButtonObject.Text == "Run")
            //{
                foreach (Type tipo in results.CompiledAssembly.GetTypes())
                {
                    if (String.Compare(tipo.Name, "Driver", false, System.Globalization.CultureInfo.InvariantCulture) == 0)
                    {
                        MethodInfo method = tipo.GetMethod("Main");
                        ParameterInfo[] typeParams = method.GetParameters();
                        if (typeParams.Length == parameters.Length)
                        {
                            if (typeParams.Length != 0)
                            {
                                param = new Object[parameters.Length];
                                for (int index = 0; index < parameters.Length; index++)
                                {
                                    try
                                    {
                                        param[index] = Convert.ChangeType(parameters[index], typeParams[index].ParameterType, System.Globalization.CultureInfo.InvariantCulture);
                                    }
                                    catch (Exception ex)
                                    {
                                        textBox3.Text = "Error : Argument Conversion Failed";
                                        return ;
                                    }
                                }
                            }
                            TextWriter temp = Console.Out;
                            var writer = new StringWriter();
                            Console.SetOut(writer);
                            method.Invoke(null, param);
                            Console.SetOut(temp);
                            textBox3.Text = writer.ToString();
                        }
                        else
                            textBox3.Text = "Error : there are differences between parameters number of function header and parameters passed for the test";
                    }
                } 
            //}
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {

        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }
    }
}